package com.boot.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.boot.common.constant.GlobalVar;
import com.boot.common.constant.MessageConstant;
import com.boot.common.constant.RedisConstant;
import com.boot.common.result.Result;
import com.boot.system.entity.SysDept;
import com.boot.system.entity.SysUser;
import com.boot.system.mapper.DeptMapper;
import com.boot.system.service.DeptService;
import com.boot.util.ConvertUtil;
import com.boot.util.RedisUtil;
import com.boot.util.SecurityUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Service("deptService")
public class DeptServiceImpl extends ServiceImpl<DeptMapper, SysDept> implements DeptService {

    private final RedisUtil redisUtil;

    /**
     * 系统启动完成后，加载部门列表缓存
     */
    @PostConstruct
    public void initDept() {
        QueryWrapper query = QueryWrapper.create().from(SysDept.class);
        query.eq("status", 1);
        List<SysDept> list = this.list(query);
        for (SysDept sysDept : list) {
            String key = StrUtil.format(RedisConstant.Dept.INFO, sysDept.getId(), sysDept.getCode());
            redisUtil.set(key, sysDept);
        }
        log.info("部门列表加载完成！");
    }

    @Override
    public List<SysDept> getDeptTree() {
        // 当前登录用户
        SysUser loginUser = SecurityUtil.getUserInfo();
        // 当前部门信息
        SysDept sysDept = this.getCache(loginUser.getDeptId(), null);
        // 部门列表
        List<SysDept> list = this.getCacheList();
        // 排序
        list.sort(Comparator.comparingInt(SysDept::getSort).reversed());
        // 过滤已禁用
        list = list.stream().filter(item -> item.getStatus().equals(1)).toList();
        return ConvertUtil.listToTree(list, "id", "pid", "children", sysDept.getPid());
    }

    @Override
    public List<SysDept> getDeptList(Map<String, Object> queryParam) {
        // 当前登录用户
        SysUser loginUser = SecurityUtil.getUserInfo();
        // 当前部门信息
        SysDept sysDept = this.getCache(loginUser.getDeptId(), null);
        // 查询条件
        QueryWrapper query = QueryWrapper.create().from(SysDept.class);
        // 模糊查询
        query.and(q -> q.and(SysDept::getName).like(queryParam.get("keywords"))
                        .or(SysDept::getCode).like(queryParam.get("keywords")),
                ObjectUtil.isNotEmpty(queryParam.get("keywords")));
        if (ObjectUtil.isNotEmpty(queryParam.get("status"))) {
            // 状态
            query.eq("status", queryParam.get("status"));
        }
        if (ObjectUtil.isNotEmpty(queryParam.get("pid"))) {
            // PID
            query.eq("pid", queryParam.get("pid"));
        }
        query.likeLeft("tree_path", StrUtil.format("{}", sysDept.getTreePath()));
        query.orderBy("sort desc", "id desc");
        List<SysDept> list = this.list(query);
        return ConvertUtil.listToTree(list, "id", "pid", "children", sysDept.getPid());
    }

    @Override
    public Result<?> addDept(Map<String, Object> dataParam) {
        //判断编码是否已存在
        if (dataParam.get("code") != null) {
            SysDept sysDeptTemp = this.mapper.selectByCode((String) dataParam.get("code"));
            if (sysDeptTemp != null) {
                //已存在
                return Result.error(MessageConstant.ROLE_EXIST);
            }
        }
        SysDept sysDept = ConvertUtil.mapToClass(dataParam, SysDept.class);
        sysDept.setCreateBy(SecurityUtil.getUid());
        sysDept.setCreateTime(GlobalVar.systemTime);
        sysDept.setUpdateBy(SecurityUtil.getUid());
        sysDept.setUpdateTime(GlobalVar.systemTime);
        //设置树路径
        if (sysDept.getPid() != null && sysDept.getPid() > 0) {
            SysDept sysDeptPid = this.getCache(sysDept.getPid(), null);
            sysDept.setTreePath(StrUtil.format("{}{},", sysDeptPid.getTreePath(), sysDeptPid.getId()));
        }
        boolean result = this.save(sysDept);
        if (result) {
            //更新缓存
            this.setCache(sysDept.getId());
        } else {
            return Result.error();
        }
        return Result.success(sysDept);
    }

    @Override
    public Result<?> updateDept(Map<String, Object> dataParam) {
        //查询原数据
        SysDept oldSysDept = this.getById(Long.valueOf(dataParam.get("id").toString()));
        //判断是否可以修改
        if (dataParam.get("code") != null && !dataParam.get("code").equals(oldSysDept.getCode())) {
            SysDept sysDeptTemp = this.mapper.selectByCode((String) dataParam.get("code"));
            if (sysDeptTemp != null) {
                //已存在
                return Result.error(MessageConstant.DEPT_EXIST);
            }
        }
        SysDept sysDept = ConvertUtil.mapToClass(dataParam, SysDept.class);
        sysDept.setUpdateBy(SecurityUtil.getUid());
        sysDept.setUpdateTime(GlobalVar.systemTime);
        //设置树路径
        if (sysDept.getPid() != null && sysDept.getPid() > 0) {
            SysDept sysDeptPid = this.getCache(sysDept.getPid(), null);
            sysDept.setTreePath(StrUtil.format("{}{},", sysDeptPid.getTreePath(), sysDeptPid.getId()));
        }
        boolean result = this.updateById(sysDept);
        if (result) {
            //更新缓存
            this.deleteCache(Collections.singletonList(sysDept.getId()));
            this.setCache(sysDept.getId());
        } else {
            return Result.error();
        }
        return Result.success(sysDept);
    }

    @Override
    public boolean deleteDept(Long id) {
        List<Long> idList = new ArrayList<>();
        idList.add(id);
        this.recursiveQuery(id, 2, idList);
        //先删除缓存
        this.deleteCache(idList);
        //数据库-逻辑删除
        this.removeByIds(idList);
        return true;
    }

    @Override
    public void recursiveQuery(Long pid, int type, List<Long> list) {
        if (type == 1) {
            //向上递归查询
            SysDept sysDept = this.getById(pid);
            if (sysDept != null) {
                //添加到列表
                list.add(sysDept.getId());
                //递归查询
                if (sysDept.getPid() != null && sysDept.getPid() > 0) {
                    recursiveQuery(sysDept.getPid(), type, list);
                }
            }
        } else if (type == 2) {
            //向下递归查询
            QueryWrapper query = QueryWrapper.create().from(SysDept.class);
            query.eq("pid", pid);
            List<SysDept> sysDeptList = this.list(query);
            for (SysDept sysDept : sysDeptList) {
                list.add(sysDept.getId());
                //递归查询
                recursiveQuery(sysDept.getId(), type, list);
            }
        }
    }

    @Override
    public List<SysDept> getCacheList() {
        List<SysDept> list = new ArrayList<>();
        String prefix = StrUtil.format(RedisConstant.Dept.INFO, "*", "*");
        Set<String> keys = redisUtil.getKeys(prefix);
        for (String key : keys) {
            SysDept sysDept = (SysDept) redisUtil.get(key);
            list.add(sysDept);
        }
        return list;
    }

    @Override
    public SysDept getCache(Long id, String code) {
        String prefix = null;
        if (id != null) {
            prefix = StrUtil.format(RedisConstant.Dept.INFO, id, "*");
        } else if (code != null) {
            prefix = StrUtil.format(RedisConstant.Dept.INFO, "*", code);
        }
        if (prefix != null) {
            //获取真实的缓存Key
            String key = null;
            Set<String> keys = redisUtil.getKeys(prefix);
            for (String item : keys) {
                key = item;
            }
            if (key != null) {
                return (SysDept) redisUtil.get(key);
            }
        }
        return null;
    }

    @Override
    public void setCache(Long id) {
        SysDept sysDept = this.getById(id);
        if (sysDept != null) {
            String key = StrUtil.format(RedisConstant.Dept.INFO, sysDept.getId(), sysDept.getCode());
            redisUtil.set(key, sysDept);
        }
    }

    @Override
    public void deleteCache(List<Long> ids) {
        for (Long id : ids) {
            String prefix = StrUtil.format(RedisConstant.Dept.INFO, id, "*");
            //获取真实的缓存Key
            String key = null;
            Set<String> keys = redisUtil.getKeys(prefix);
            for (String item : keys) {
                key = item;
            }
            if (key != null) {
                //删除
                redisUtil.delete(key);
            }
        }
    }
}
